﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.ServiceModel.DomainServices.Client;
using System.Linq;
using Scoreboard.Interfaces;
using Scoreboard.Model;
using Scoreboard.Data;
using Scoreboard.Basement;
using Scoreboard.Basement.ViewModels;
using Microsoft.Practices.Composite.Presentation.Commands;
using Scoreboard.CommonViews;
using Microsoft.Practices.Composite.Events;
using Scoreboard.Basement.Events;

namespace Scoreboard.Rating
{
	public class ViewModel : PageViewModel
	{
		private IUserRepository _userRepository;
		private IGameRepository _gameRepository;

		private IEnumerable<PlayerViewModel> _ratingTable;
		private bool _isLoadingRatingTable;

		private IEnumerable<Game> _games;
		private bool _isLoadingGames;

		public ViewModel(IUserRepository userRepository, IGameRepository gameRepository)
		{
			AddResultCommand = new DelegateCommand<object>(AddResultCommandHandler);

			_userRepository = userRepository;
			_gameRepository = gameRepository;

			AddUpdater(EntityTypes.Users, LoadRatingTable);
			AddUpdater(EntityTypes.RatingGames, LoadGames);			

			RefreshCommands();

			var eventAggregator = ServiceLocator.Get<IEventAggregator>();
			var userAuthenticatedEvent = eventAggregator.GetEvent<UserAuthenticatedEvent>();

			userAuthenticatedEvent.Subscribe(UserAuthenticatedHandler);
		}

		public ICommand AddResultCommand { get; private set; }

		public IEnumerable<PlayerViewModel> RatingTable
		{
			get
			{
				if (_ratingTable == null)
				{
					LoadRatingTable();
				}
				return _ratingTable;
			}
			set
			{
				_ratingTable = value;
				FirePropertyChanged("RatingTable");
			}
		}

		public IEnumerable<Game> Games
		{
			get
			{
				if (_games == null)
				{
					LoadGames();
				}
				return _games;
			}
			set
			{
				_games = value;
				FirePropertyChanged("Games");
			}
		}

		public void UserAuthenticatedHandler(bool isRegistered)
		{
			if (_ratingTable != null)
			{
				foreach (var vm in _ratingTable)
				{
					vm.NotifyCurrentUserChanged();
				}
			}
		}

		private void LoadRatingTable()
		{
			if (_isLoadingRatingTable)
			{
				return;
			}
			_userRepository.GetRatingTable(LoadRatingTableCompleted);
			_isLoadingRatingTable = true;
		}

		protected override string Name
		{
			get
			{
				return "Rating View Model";
			}
		}

		protected override void RefreshCommands()
		{
			Commands.Clear();			
			if (WebContext.Current.IsUserRegistered)
			{
				Commands.Add(new UserCommand("Добавить результат", AddResultCommand));
			}
		}

		private void LoadRatingTableCompleted(LoadOperation<User> operation)
		{
			RatingTable = operation.Entities
				.Select(u => new PlayerViewModel(u))
				.ToList();
			
			int i = 1;
			foreach (var pwm in RatingTable)
			{
				pwm.Position = i;
				i++;
			}
			
			_isLoadingRatingTable = false;
		}

		private void LoadGames()
		{
			if (_isLoadingGames)
			{
				return;
			}

			_gameRepository.GetRatingGames(LoadGamesCompleted);
			_isLoadingGames = true;
		}

		private void LoadGamesCompleted(LoadOperation<Game> operation)
		{
			Games = operation.Entities;
			_isLoadingGames = false;
		}

		private void AddResultCommandHandler(object parameter)
		{
			var dialogService = ServiceLocator.Get<IDialogService>();

			var viewModel = new AddResultDialogViewModel(_userRepository, _gameRepository, AddResultCallback);
			var addResultDialog = new AddResultDialog(viewModel);
			dialogService.ShowDialog(addResultDialog);
		}

		private void AddResultCallback(InvokeOperation operation)
		{
			if (!operation.HasError)
			{
				var eventAggregator = ServiceLocator.Get<IEventAggregator>();
				var dataChangedEvent = eventAggregator.GetEvent<DataChangedEvent>();
				dataChangedEvent.Publish(EntityTypes.RatingGames);
				dataChangedEvent.Publish(EntityTypes.Users);				
			}
		}
	}
}
